//---------------------------------------------------------------------
// File: ExecuteCommandStep.cs
// 
// Summary: 
//
//---------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, WHETHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//---------------------------------------------------------------------

namespace Microsoft.Services.BizTalkApplicationFramework.BizUnit
{
	using System;
	using System.Xml;
	using System.Diagnostics;

	/// <summary>
	/// The ExecuteCommandStep executes a program from the command line, command line arguments may be supplied also.
	/// </summary>
	/// 
	/// <remarks>
	/// The following shows an example of the Xml representation of this test step.
	/// 
	/// <code escaped="true">
	/// <TestStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.ExecuteCommandStep">
	///		<ProcessName>processName</ProcessName>
	///		<ProcessParams>-a32 -bFooBar</ProcessParams>
	///		<WorkingDirectory>..\..\setup</WorkingDirectory>
	/// </TestStep>
	///	</code>
	///	
	///	<list type="table">
	///		<listheader>
	///			<term>Tag</term>
	///			<description>Description</description>
	///		</listheader>
	///		<item>
	///			<term>ProcessName</term>
	///			<description>The name of the program to execute</description>
	///		</item>
	///		<item>
	///			<term>ProcessParams</term>
	///			<description>The command line paramters</description>
	///		</item>
	///		<item>
	///			<term>WorkingDirectory</term>
	///			<description>The working directory to run the program from</description>
	///		</item>
	///	</list>
	///	</remarks>

	public class ExecuteCommandStep : ITestStep
	{
		/// <summary>
		/// ITestStep.Execute() implementation
		/// </summary>
		/// <param name='testConfig'>The Xml fragment containing the configuration for this test step</param>
		/// <param name='context'>The context for the test, this holds state that is passed beteen tests</param>
		public void Execute(XmlNode testConfig, Context context)
		{
			string processName = context.ReadConfigAsString( testConfig, "ProcessName" );
			string processParams = context.ReadConfigAsString( testConfig, "ProcessParams");
			string workingDirectory = context.ReadConfigAsString( testConfig, "WorkingDirectory" );

			context.LogInfo("ExecuteCommandStep about to execute the command: {0} params: {1}, working directory: {2}", processName, processParams, workingDirectory);

			Process process = new Process();
			process.StartInfo.UseShellExecute = false;
			process.StartInfo.RedirectStandardOutput = true;
			process.StartInfo.CreateNoWindow = true;
			process.StartInfo.Arguments = processParams; 
			process.StartInfo.FileName = processName;              
			process.StartInfo.WorkingDirectory = workingDirectory;

			process.Start();

            string output = process.StandardOutput.ReadToEnd();
			process.WaitForExit();
			int exitCode = process.ExitCode;

			if ( 0 != exitCode )
			{
				throw new ApplicationException( string.Format("ExecuteCommandStep received an exit code: {0} while executing process {1} {2}\n\nOutput: {3}", exitCode, processName, processParams, output) );
			}

			context.LogInfo("ExecuteCommandStep {0} output:\n{1}", processName, output );
		}
	}
}
